from typing import Dict, Any, Callable

from ys_python.common.base.single_ton import SingleTon


class HasNameError(Exception):
    """
    名称存在异常
    """

    def __init__(self, error_info):
        super(HasNameError, self).__init__(error_info)
        self.error_info = error_info

    def __str__(self):
        return "{} 名称已存在".format(self.error_info)


@SingleTon
class Instance:
    """
    单例辅助管理组件
    """
    _instance_dict: Dict[str, Any] = {}

    def __has_name(self, name: str) -> bool:
        return name in self._instance_dict

    def get(self, name: str):
        """
        根据指定名称获取单例
        :param name: 名称 唯一
        :return: None 未找到，或者指定单例对象
        """
        if self.__has_name(name):
            return self._instance_dict[name]
        return None

    def set(self, name: str, i):
        """
        设置单例
        :param name: 名称 唯一
        :param i: 单例对象
        :return: 名称重复时会抛出异常
        """
        if self.__has_name(name):
            raise HasNameError(name)
        else:
            self._instance_dict[name] = i

    def get_or_set(self, name: str, i):
        """
        设置或获取单例
        :param name:
        :param i: 单例实例，只有在不存在时
        :return: name 所指向的 单例实例
        """
        if not self.__has_name(name):
            self.set(name, i)
        return self.get(name)

    def get_or_set_func(self, name: str, func: Callable[[], Any]):
        """
        设置或获取单例。
        当单例不存在
        :param name: 名称 唯一
        :param func: 需要执行的函数，执行后生成实例
        :return: name 所指向的 单例实例
        """
        if not self.__has_name(name):
            self.set(name, func())
        return self.get(name)

    def clear(self):
        """
        清空所有单例信息
        !慎用!
        :return:
        """
        self._instance_dict.clear()

    def clear_one(self, name: str) -> None:
        if self.__has_name(name):
            del (self._instance_dict[name])
